{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw_data_X = [[3.393533211, 2.331273381],\n",
    "              [3.110073483, 1.781539638],\n",
    "              [1.343808831, 3.368360954],\n",
    "              [3.582294042, 4.679179110],\n",
    "              [2.280362439, 2.866990263],\n",
    "              [7.423436942, 4.696522875],\n",
    "              [5.745051997, 3.533989803],\n",
    "              [9.172168622, 2.511101045],\n",
    "              [7.792783481, 3.424088941],\n",
    "              [7.939820817, 0.791637231]\n",
    "             ]\n",
    "raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train = np.array(raw_data_X)\n",
    "y_train = np.array(raw_data_y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(x = X_train[y_train == 0,0],y = X_train[y_train == 0,1],color = \"b\")\n",
    "plt.scatter(x = X_train[y_train == 1,0],y = X_train[y_train == 1,1],color = \"r\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "此时新增一个数据点，以当前数据的分布规则判断新数据点的分类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.array([8.093607318, 3.365731514])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(x = X_train[y_train == 0,0],y = X_train[y_train == 0,1],color = \"b\")\n",
    "plt.scatter(x = X_train[y_train == 1,0],y = X_train[y_train == 1,1],color = \"r\")\n",
    "plt.scatter(x[0],x[1],color= \"black\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## KNN算法实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 1, 1, 1])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from math import sqrt\n",
    "from collections import Counter\n",
    "distances = []\n",
    "# 计算新增点x到每个点之间的距离，并储存到一个列表中\n",
    "for x_train in X_train:\n",
    "    d = sqrt(np.sum((x_train - x)**2))\n",
    "    distances.append(d)\n",
    "    \n",
    "# 对列表中的距离进行排序，选出距离最近的n个点\n",
    "nearest = y_train[np.argsort(distances)]\n",
    "topK_y = nearest[:4]\n",
    "topK_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = Counter(topK_y) #返回一个字典\n",
    "\n",
    "# 返回和新增点最接近的点的标签\n",
    "c.most_common()[0][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4.812566907609877,\n",
       " 5.229270827235305,\n",
       " 6.749798999160064,\n",
       " 4.6986266144110695,\n",
       " 5.83460014556857,\n",
       " 1.4900114024329525,\n",
       " 2.354574897431513,\n",
       " 1.3761132675144652,\n",
       " 0.3064319992975,\n",
       " 2.5786840957478887]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "distances"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 封装KNN算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import sqrt\n",
    "from collections import Counter\n",
    "def KNNClassifier(x,X_train,y_train,k):\n",
    "    # 使用列表存储各个点与新增点的距离\n",
    "    dist = [np.sqrt(np.sum((x - x_train)**2)) for x_train in X_train]\n",
    "    # 排序选出距离最近的k个点\n",
    "    k_nearest = y_train[np.argsort(dist)[:k]]\n",
    "    # 对距离最近的k个点的标签统计次数\n",
    "    votes = Counter(k_nearest)\n",
    "    # 返回属性个数最多的标签\n",
    "    predict_y = votes.most_common(1)[0][0]\n",
    "    return predict_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "KNNClassifier(x,X_train,y_train,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 运行pycharm中封装的KNN算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "%run ./encapsulations/KNN.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "import numpy as np\r\n",
      "from math import sqrt\r\n",
      "from collections import Counter\r\n",
      "\r\n",
      "def KNN_classify(x,X_train,y_train,k):\r\n",
      "\r\n",
      "    assert 1 <= k <= X_train.shape[0], \"k must be valid\"\r\n",
      "    assert X_train.shape[0] == y_train.shape[0],\"the size of X_train must equal to the size of y_train\"\r\n",
      "    assert X_train.shape[1] == x.shape[0],\"the feature number of x must equal to X_train\"\r\n",
      "\r\n",
      "    distances = [sqrt(np.sum((x - x_train)**2)) for x_train in X_train]\r\n",
      "    nearest = np.argsort(distances)[:k]\r\n",
      "    topK_y = y_train[nearest]\r\n",
      "    votes = Counter(topK_y).most_common()[0][0]\r\n",
      "    return votes\r\n"
     ]
    }
   ],
   "source": [
    "%cat ./encapsulations/KNN.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "KNN_classify(x,X_train,y_train,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用Scikit-learn中的KNN算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "KNN_classifier = KNeighborsClassifier(n_neighbors=6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "                     metric_params=None, n_jobs=None, n_neighbors=6, p=2,\n",
       "                     weights='uniform')"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "KNN_classifier.fit(X_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "KNN_classifier.predict(x.reshape(1,-1))  \n",
    "#新版本的sklearn已经不支持直接传入一个数进行KNN预测了，需要传入一个数组，因此需要reshape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 重新整理我们的KNN算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "import numpy as np\r\n",
      "from math import sqrt\r\n",
      "from collections import Counter\r\n",
      "\r\n",
      "class KNNClassifier:\r\n",
      "\r\n",
      "    def __init__(self,k):\r\n",
      "        \"\"\"初始化KNN分类器\"\"\"\r\n",
      "        assert k >= 1,\"k must be valid\"\r\n",
      "        self.k = k\r\n",
      "        self._X_train = None\r\n",
      "        self._y_train = None\r\n",
      "\r\n",
      "    def fit(self,X_train,y_train):\r\n",
      "        \"\"\"根据训练集X_train和y_train训练KNN分类器\"\"\"\r\n",
      "        assert X_train.shape[0] == y_train.shape[0], \"the size of X_train must equal to the size of y_train\"\r\n",
      "        assert self.k <= X_train.shape[0], \"the size of X_train must be at least k.\"\r\n",
      "\r\n",
      "        self._X_train = X_train\r\n",
      "        self._y_train = y_train\r\n",
      "        return self\r\n",
      "\r\n",
      "    def predict(self,X_predict):\r\n",
      "        \"\"\"给定待预测数据集X_predict,返回表示X_predict的结果向量\"\"\"\r\n",
      "        assert self._X_train is not None and self._X_train is not None,\\\r\n",
      "            \"must fit before predict\"\r\n",
      "        assert X_predict.shape[1] == self._X_train.shape[1],\\\r\n",
      "            \"the feature number of X_predict must be equal to X_train\"\r\n",
      "\r\n",
      "        y_predict = [self._predict(x) for x in X_predict]\r\n",
      "        return np.array(y_predict)\r\n",
      "\r\n",
      "    def _predict(self,x):\r\n",
      "        \"\"\"给单个的待预测数据x,返回x_predict的预测结果值\"\"\"\r\n",
      "        assert x.shape[0] == self._X_train.shape[1],\\\r\n",
      "            \"the feature number of x must be equal to X_train\"\r\n",
      "\r\n",
      "        distances = [sqrt(np.sum((x - x_train)**2)) for x_train in self._X_train]\r\n",
      "        nearest = np.argsort(distances)[:self.k]\r\n",
      "        topK_y = self._y_train[nearest]\r\n",
      "        votes = Counter(topK_y).most_common()[0][0]\r\n",
      "        return votes\r\n",
      "\r\n",
      "    def __repr__(self):\r\n",
      "        return \"KNN(k=%d)\" % self.k\r\n"
     ]
    }
   ],
   "source": [
    "%cat ./encapsulations/KNN.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "%run ./encapsulations/KNN.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn_clf= KNNClassifier(k=6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNN(k=6)"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_clf.fit(X_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_clf.predict(x.reshape(1,-1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
